package com.shxy.rlzy.controller;


import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shxy.rlzy.common.lang.Result;
import com.shxy.rlzy.controller.salary.Item;
import com.shxy.rlzy.controller.salary.QueryParam;
import com.shxy.rlzy.entity.*;
import com.shxy.rlzy.service.*;
import com.shxy.rlzy.utils.DecimalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author tanhao
 * @since 2022-02-16
 */
@RestController
@RequestMapping("/salary")
public class SalaryController extends BaseController {
    @Autowired
    private IEmployeeInfoService employeeInfoService;
    @Autowired
    private IDepartService departService;
    @Autowired
    private ISalaryService salaryService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IEmployeeUserService employeeUserService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IUserRoleService userRoleService;

    /**
     * 获取部门员工列表
     * @param departId
     * @return
     */
    @GetMapping("/employee/items/{departId}")
    public Result getEmployees(@PathVariable Long departId) {
        Depart depart = departService.getById(departId);    // 查询部门信息
        QueryWrapper<EmployeeInfo> qw = new QueryWrapper<EmployeeInfo>().eq("depart_id", departId);
        List<EmployeeInfo> employees = employeeInfoService.list(qw);
        // 将员工信息转换成item结构
        List<JSONObject> items = employees.stream().map(employee -> {
            JSONObject emp = new JSONObject();
            emp.set("id", employee.getId());
            emp.set("name", employee.getName());
            return emp;
        }).collect(Collectors.toList());
        // 构造返回结果
        JSONObject result = new JSONObject();
        result.set("clerkId", depart.getClerkId());
        result.set("employees", items);
        return Result.succ(result);
    }

    /**
     * 设置部门工资员
     * @param departId
     * @param clerkId
     * @return
     */
    @PutMapping("/depart/setClerk/{departId}/{clerkId}")
    @PreAuthorize("hasAnyAuthority('wage:bonus:clerk')")
    public Result setClerk(@PathVariable Long departId, @PathVariable Long clerkId) {
        // 1、判断是否有工资员角色
        Role clerkRole = roleService.getByCode("clerk");
        if(clerkRole == null) {
            Result.fail("没有工资员角色");
        }

        // 2、获取部门工资员员工信息
        EmployeeInfo employeeInfo = employeeInfoService.getById(clerkId);

        // 3、将员工信息设置为用户信息
        User clerk = userService.importFromEmployee(employeeInfo);

        // 4、将员工设置为工资员
        if(!userRoleService.set(clerk, clerkRole)) {
            return Result.fail("设置员工为工资员失败");
        }

        // 5、更新部门工资员编号
        if(!departService.setClerk(departId, clerkId)) {
            return Result.fail("设置部门工资员失败");
        }

        return Result.succ("设置成功");
    }

    /**
     * 获取部门列表
     * @return
     */
    @GetMapping("/depart/items")
    public Result getDepartItems() {
        List<Depart> depts = departService.list().stream().filter(Depart::isHasBonus).collect(Collectors.toList());
        return Result.succ(depts);
    }

    /**
     * 根据条件查询员工工资信息列表
     * @param param
     * @return
     */
    @PostMapping("/list")
    public Result getSalarys(@RequestBody QueryParam param) {
        List<Salary> list = salaryService.getList(param.getDepartId(), param.getGender(), param.getName(), param.getPhone());
        List<JSONObject> objs = list.stream().map(salary -> convertSalary(salary)).collect(Collectors.toList());
        return Result.succ(objs);
    }

    /**
     * 初始化
     * @return
     */
    @PutMapping("/init")
    @PreAuthorize("hasAnyAuthority('wage:salary:init')")
    public Result initSalarys() {
        salaryService.initBatch();
        return Result.succ("导入成功");
    }

    /**
     * 修改员工工资信息
     * @return
     */
    @PutMapping("/modify")
    @PreAuthorize("hasAnyAuthority('wage:salary:save')")
    public Result saveSalary(@RequestBody Salary salary) {
        if(salaryService.updateById(salary)){
            return Result.succ("修改工资信息成功");
        }
        return Result.fail("修改工资信息失败");
    }

    /**
     * 返回结果转换
     * @param salary
     * @return
     */
    private JSONObject convertSalary(Salary salary) {
        JSONObject obj = JSONUtil.parseObj(salary);
        obj.remove("employeeInfo");
        obj.set("id", salary.getId());
        obj.set("name", salary.getEmployeeInfo().getName());
        obj.set("age", salary.getEmployeeInfo().getAge());
        obj.set("depart", salary.getEmployeeInfo().getDepart().getName());
        obj.set("phone", salary.getEmployeeInfo().getPhone());
        return obj;
    }

    /**
     *  导入数据
     * @return
     */
    @PutMapping("/import")
    @PreAuthorize("hasAnyAuthority('wage:salary:import')")
    public Result importData(@RequestBody List<Item> items) {
        // 0、去重
        items = items.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Item::getIdCard))), ArrayList::new));
        List<Salary> salaries = new ArrayList<>();
        // 1、复制参数
        for(Item item: items) {
            Salary salary = salaryService.getByIdCard(item.getIdCard());
            if(salary != null) {
                BeanUtils.copyProperties(item, salary);
                salaries.add(salary);
            }
        }

        // 3、格式化数字
        salaries = salaries.stream().map(salary -> salaryDecimalFormat(salary)).collect(Collectors.toList());

        // 4、存入数据库
        salaryService.updateBatchById(salaries);

        // 5、返回结果
        return Result.succ(String.format("成功导入%d条工资数据。", salaries.size()));
    }

    /**
     * 数字格式化转换
     * @param salary
     * @return
     */
    private Salary salaryDecimalFormat(Salary salary) {
        salary.setGradeSalary(DecimalUtils.formatDecimal(salary.getGradeSalary(), 10, RoundingMode.valueOf(2)));
        salary.setPostSalary(DecimalUtils.formatDecimal(salary.getPostSalary(), 10, RoundingMode.valueOf(2)));
        salary.setEnhanced(DecimalUtils.formatDecimal(salary.getEnhanced(), 10, RoundingMode.valueOf(2)));

        salary.setBaseMerit(DecimalUtils.formatDecimal(salary.getBaseMerit(), 10, RoundingMode.valueOf(2)));
        salary.setRewardOrPunish(DecimalUtils.formatDecimal(salary.getRewardOrPunish(), 10, RoundingMode.valueOf(2)));
        salary.setStudentFee(DecimalUtils.formatDecimal(salary.getStudentFee(), 10, RoundingMode.valueOf(2)));
        salary.setYearMerit(DecimalUtils.formatDecimal(salary.getYearMerit(), 10, RoundingMode.valueOf(2)));
        salary.setClassFee(DecimalUtils.formatDecimal(salary.getClassFee(), 10, RoundingMode.valueOf(2)));
        salary.setOvertimePay(DecimalUtils.formatDecimal(salary.getOvertimePay(), 10, RoundingMode.valueOf(2)));

        salary.setInsurance1(DecimalUtils.formatDecimal(salary.getInsurance1(), 10, RoundingMode.valueOf(2)));
        salary.setInsurance2(DecimalUtils.formatDecimal(salary.getInsurance2(), 10, RoundingMode.valueOf(2)));
        salary.setInsurance3(DecimalUtils.formatDecimal(salary.getInsurance3(), 10, RoundingMode.valueOf(2)));
        salary.setInsurance4(DecimalUtils.formatDecimal(salary.getInsurance4(), 10, RoundingMode.valueOf(2)));
        salary.setInsurance5(DecimalUtils.formatDecimal(salary.getInsurance5(), 10, RoundingMode.valueOf(2)));

        salary.setRetention1(DecimalUtils.formatDecimal(salary.getRetention1(), 10, RoundingMode.valueOf(2)));
        salary.setRetention2(DecimalUtils.formatDecimal(salary.getRetention2(), 10, RoundingMode.valueOf(2)));
        salary.setRetention3(DecimalUtils.formatDecimal(salary.getRetention3(), 10, RoundingMode.valueOf(2)));
        salary.setRetention4(DecimalUtils.formatDecimal(salary.getRetention4(), 10, RoundingMode.valueOf(2)));
        salary.setRetention5(DecimalUtils.formatDecimal(salary.getRetention5(), 10, RoundingMode.valueOf(2)));
        salary.setRetention6(DecimalUtils.formatDecimal(salary.getRetention6(), 10, RoundingMode.valueOf(2)));
        salary.setRetention7(DecimalUtils.formatDecimal(salary.getRetention7(), 10, RoundingMode.valueOf(2)));
        salary.setRetention8(DecimalUtils.formatDecimal(salary.getRetention8(), 10, RoundingMode.valueOf(2)));
        salary.setRetention9(DecimalUtils.formatDecimal(salary.getRetention9(), 10, RoundingMode.valueOf(2)));
        salary.setRetention10(DecimalUtils.formatDecimal(salary.getRetention10(), 10, RoundingMode.valueOf(2)));
        salary.setRetention11(DecimalUtils.formatDecimal(salary.getRetention11(), 10, RoundingMode.valueOf(2)));
        salary.setRetention12(DecimalUtils.formatDecimal(salary.getRetention12(), 10, RoundingMode.valueOf(2)));
        salary.setRetention13(DecimalUtils.formatDecimal(salary.getRetention13(), 10, RoundingMode.valueOf(2)));
        salary.setRetention14(DecimalUtils.formatDecimal(salary.getRetention14(), 10, RoundingMode.valueOf(2)));
        salary.setRetention15(DecimalUtils.formatDecimal(salary.getRetention15(), 10, RoundingMode.valueOf(2)));
        salary.setRetention16(DecimalUtils.formatDecimal(salary.getRetention16(), 10, RoundingMode.valueOf(2)));

        return salary;
    }
}
